#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <pthread.h>
#include "pool.h"
 
static tpool_t *tpool = NULL;//整个线程池
 
/* 工作者线程函数, 从任务链表中取出任务并执行 */
static void * routine(void *arg)
{
    tpool_work_t *work = calloc(1, sizeof(tpool_work_t)); 

    while(1)
    {
        if(!tpool->queue_head) {
            if(!work) {
                continue;
            } else {
                break;
            }
        }

        work = tpool->queue_head;
        tpool->queue_head = (tpool_work_t*) work->next;//指针跳到下一个位置

        printf("work begin to do task!\n");
        work->do_task(work->arg);//取得这个链表的结点，调用此任务的任务函数dotask输出字符串
        free(work);
    }
    printf("a thread finished!\n");
 
    return NULL;
}


// 创建线程池

int tpool_create(int max_thr_num)
{
    int i;
 
    tpool = calloc(1, sizeof(tpool_t)*2);
    //tpool = (tpool_t*)malloc( 2 * sizeof(tpool_t));
	//使用calloc而不是malloc是因为calloc在开辟内存空间后可以自动初始化内存
	//因为开辟一个线程池，所以前面的参数是1 
    if (!tpool)
    {
        printf("%s: calloc failed\n", __FUNCTION__);
        exit(1);
    }
 
    /* 初始化 */
    tpool->max_thr_num = max_thr_num;
    tpool->queue_head = NULL;
    
    /* 创建线程池里面的线程 */
    tpool->thr_id = calloc(max_thr_num, sizeof(pthread_t));
    //tpool->thr_id = (pthread_t*)malloc( (max_thr_num + 1) * sizeof(pthread_t));



    for (i = 0; i < max_thr_num; i++)
    {
        if (pthread_create(&tpool->thr_id[i], NULL, routine, (void *)(long)i) != 0)
		//指向线程标识符的指针 线程属性 线程运行函数的地址 运行函数的参数arg
        {
            printf("%s:pthread_create failed, errno:%d, error:%s\n", __FUNCTION__,
                   errno, strerror(errno));
            exit(1);
        }
        else {
            printf("pthread %d create succeed!\n", i);
        }
		//线程的创建成功 有一个输出的提示
 
    }
 
    return 0;
}
 
/* 销毁线程池 */
void tpool_destroy()
{
    int i;
    tpool_work_t *member;
 
    
    for (i = 0; i < tpool->max_thr_num; ++i)
    {
        printf("waiting for thread %d exit\n",i );
        pthread_join(tpool->thr_id[i], NULL);//等待线程池里面的所有线程退出  
        
    }
    free(tpool->thr_id);//id本身也是指针 也要free掉
    while(tpool->queue_head)
    {
        printf("linklist is not destroyed!\n");
        member = tpool->queue_head;
        tpool->queue_head = tpool->queue_head->next;
        free(member);
    }

 
    free(tpool);//最后把整个线程池结构给free
}
 
/* 向线程池添加任务 */
int tpool_add_work(void *(*routine)(void *), void *arg)
{
    tpool_work_t *work, *member;

    work = malloc(sizeof(tpool_work_t));
    //先将要添加进去的任务的空间给开辟
	//下面是初始化 

    work->do_task = routine;
    work->arg = arg;
    work->next = NULL;

    member = tpool->queue_head;
    if (!member)
    {
        tpool->queue_head = work;
        printf("work adding succeed!\n");
    }
    else
    {
        while(member->next)
        {
            member = member->next;
        }
        member->next = work;
        printf("work adding succeed!\n");
    }
    //找到要添加的位置 如果链表为空则是置于链表头部 如果不为空则置于尾部 
    
    
    return 0;
}




